package org.lex.tinyscript.command;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.lex.tinyscript.TinyScriptException;

public class CommandParser {
	private static final Map<String, ScriptCommand> map;
	private static final char ARG_BEGIN = '<';
	private static final char ARG_END = '>';
	private static Pattern ARG_PATTERN;

	static {
		map = new HashMap<String, ScriptCommand>();
		registerCommand(new DeleteFileCommand());
		registerCommand(new MoveFileCommand());
		registerCommand(new JavaCommand());

		ARG_PATTERN = Pattern.compile("[" + ARG_BEGIN + "][^" + ARG_END + "]*["
				+ ARG_END + "]");
	}

	private static void registerCommand(ScriptCommand task) {
		map.put(task.getCommand(), task);
	}

	/*
	 * line:= command <file> <file>...
	 */
	public ScriptCommand parse(String line) throws TinyScriptException,
			CloneNotSupportedException {
		line = line.trim();
		String commandName = this.parseCommandName(line);
		final ScriptCommand command = map.get(commandName);
		if (null == command) {
			throw new TinyScriptException("Command [" + commandName + "] unkown: "
					+ line);
		}
		String[] args = this.parseArguments(line);
		ScriptCommand result = command.clone();
		result.setArguments(args);
		return result;
	}

	private String parseCommandName(String line) {
		int firstArgumentStartIndex = line.indexOf(ARG_BEGIN);
		if (firstArgumentStartIndex < 0) {
			firstArgumentStartIndex = line.length();
		}
		return line.substring(0, firstArgumentStartIndex).trim();
	}

	private String[] parseArguments(String line) {
		Matcher matcher = ARG_PATTERN.matcher(line);
		List<String> results = new ArrayList<String>(2);
		while (matcher.find()) {
			String arg = line.substring(matcher.start() + 1, matcher.end());
			results.add(arg.trim());
		}
		return results.toArray(new String[results.size()]);
	}
}
